﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Wf5.Engine.Common;
using Wf5.Engine.Utility;

using FCDB.Entity;
using FCDB.Repository;

namespace Wf5.Engine.Business
{
    /// <summary>
    /// 活动实例管理类
    /// </summary>
    public class ActivityInstanceManager
    {
        #region ActivityInstanceManager 属性

        private WfActivityInstanceRepository _activityInstanceRepository;
        private WfActivityInstanceRepository ActivityInstanceRepository
        {
            get
            {
                if (_activityInstanceRepository == null)
                {
                    _activityInstanceRepository = new WfActivityInstanceRepository();
                }
                return _activityInstanceRepository;
            }
        }
        #endregion
       
        #region ActivityInstanceManager 构造函数
        public ActivityInstanceManager()
        {
        }
        #endregion

        #region ActivityInstanceManager 活动实例数据获取
        internal WfActivityInstance GetById(long activityInstanceID)
        {
            
            try
            {
                return ActivityInstanceRepository.Get<WfActivityInstance>(activityInstanceID);
            }
            catch (System.Exception e)
            {
                throw new ApplicationException(string.Format("数据读取方法GetById发生错误，请查看内部异常: {0}", e.Message), e);
            }
           
        } 
        /// <summary>
        /// 判断有活动实例是否在运行状态
        /// </summary>
        /// <param name="activityGUID"></param>
        /// <returns></returns>
        internal WfActivityInstance GetActivityWithRunningState(long processInstanceID,Guid activityGUID)
        {
            return ActivityInstanceRepository.GetActivityWithRunningState(processInstanceID, activityGUID, (short)NodeStateEnum.Running); 
        }

        /// <summary>
        /// 获取流程实例中运行的活动节点
        /// </summary>
        /// <param name="appInstanceID"></param>
        /// <param name="processGUID"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        internal IEnumerable<WfActivityInstance> GetProcessRunningActivityList(long appInstanceID,
            Guid processGUID)
        {
            //activityState: 1-ready（准备）, 2-running（）运行；
            //  var whereSql = @"WHERE AppInstanceID = @appInstanceID 
            //   AND ProcessGUID = @processGUID
            //     AND (State=1 OR State=2)"; 
            var instanceList = ActivityInstanceRepository.GetProcessRunningActivityList(appInstanceID,processGUID);  
            return instanceList;
        }

        /// <summary>
        /// 分页获取活动实例数据
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        internal IEnumerable<WfActivityInstance> GetAcitivityInstancePaged(TaskQueryEntity query)
        {
//            ISession session = SessionFactory.CreateSession();
//            var whereSql = @" WHERE AppInstanceID = @appInstanceID
//                            AND ProcessGUID = @processGUID";
//            var orderBySql = "ORDER BY CreatedDateTime DESC";

            //var entityList = ActivityInstanceRepository.GetPage<WfActivityInstance>(query.PageIndex, query.PageSize,
            //    whereSql, new
            //    {
            //        appInstanceID = query.AppInstanceID,
            //        processGUID = query.ProcessGUID
            //    },
            //    orderBySql,
            //    session.Connection, session.Transaction);
            return ActivityInstanceRepository.GetAcitivityInstancePaged(query.PageIndex, query.PageSize, query.AppInstanceID, query.ProcessGUID);
             
        }

        internal CurrentRunningNodeMapComplex GetCurrentRunningNodeMap(WfActivityInstance runningNode, 
            WfAppRunner runner)
        {
            var node = new CurrentRunningNodeMapComplex();

            //判断当前运行节点是否是我的任务
            var taskManager = new TaskManager();
            node.IsMine = taskManager.IsMine(runningNode.ID, runner.UserID);

            //获取上一步节点列表
            bool hasGatewayNode = false;
            var tim = new TransitionInstanceManager();
            node.PreviousActivityInstance = tim.GetPreviousActivityInstance(runningNode, out hasGatewayNode).ToList();

            //获取下一步步骤列表
            var processModel = new ProcessModel(runningNode.ProcessGUID);
            node.NextActivityTree = processModel.GetNextActivityTree(runningNode.ActivityGUID, runner.Conditions);

            return node;
        }

        //internal IEnumerable<ActivityInstanceEntity> GetPreviousActivityInstance(ActivityInstanceEntity runningNode)
        //{
        //    var tim = new TransitionInstanceManager();
        //    var nodeList = tim.GetPreviousActivityInstance(runningNode);
        //    return nodeList;
        //}
        #endregion

        /// <summary>
        /// 创建活动实例的对象
        /// </summary>
        /// <param name="activity"></param>
        /// <param name="processInstance"></param>
        /// <returns></returns>
        internal WfActivityInstance CreateActivityInstanceObject(string appName,
            long appInstanceID,
            long processInstanceID,
            ActivityEntity activity,
            WfLogonUser logonUser)
        {
            WfActivityInstance instance = new WfActivityInstance();
            instance.ID = IDCreateLogic.GenerateID("WfActivityInstance", "流程活动ID");
            instance.ActivityGUID = activity.ActivityGUID;
            instance.ActivityName = activity.ActivityName;
            instance.ActivityType = (short)activity.NodeType;
            instance.GatewayDirectionTypeID = (short)activity.GatewayDirectionType;
            instance.ProcessGUID = activity.ProcessGUID;
            instance.AppName = appName;
            instance.AppInstanceID = appInstanceID;
            
            instance.ProcessInstanceID = processInstanceID;
            instance.TokensRequired = 1;
            instance.TokensHad = 1;
            instance.CreatedByUserID = logonUser.UserID;
            instance.CreatedByUserName = logonUser.UserName;
            instance.CreatedDateTime = System.DateTime.Now;
            instance.State = (short)NodeStateEnum.Ready;
            instance.CanRenewInstance = 0;

            return instance;
        }

        /// <summary>
        /// 更新活动节点的Token数目
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="logonUser"></param>
        /// <param name="wfLinqDataContext"></param>
        internal void IncreaseTokensHad(long activityInstanceID,WfLogonUser logonUser )
        {
            WfActivityInstance activityInstance = GetById(activityInstanceID);
            activityInstance.TokensHad += 1;
            Update(activityInstance);
        }

        #region 活动实例中间状态设置
        /// <summary>
        /// 活动实例被读取
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="logonUser"></param>
        /// <param name="session"></param>
        internal void Read(long activityInstanceID, WfLogonUser logonUser )
        {
            SetActivityState(activityInstanceID, NodeStateEnum.Running, logonUser);
        }

        /// <summary>
        /// 撤销活动实例
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="logonUser"></param>
        /// <param name="session"></param>
        internal void Withdraw(long activityInstanceID,WfLogonUser logonUser)
        {
            SetActivityState(activityInstanceID, NodeStateEnum.Withdrawed, logonUser);
        }

        /// <summary>
        /// 退回活动实例
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="logonUser"></param>
        /// <param name="session"></param>
        internal void Reject(long activityInstanceID,
            WfLogonUser logonUser)
        {
            SetActivityState(activityInstanceID, NodeStateEnum.Rejected, logonUser);
        }

        /// <summary>
        /// 设置活动实例状态
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="nodeState"></param>
        /// <param name="logonUser"></param>
        /// <param name="session"></param>
        private void SetActivityState(long activityInstanceID,NodeStateEnum nodeState,WfLogonUser logonUser )
        {
            var activityInstance = GetById(activityInstanceID);
            activityInstance.State = (short)nodeState;
            activityInstance.LastUpdatedByUserID = logonUser.UserID;
            activityInstance.LastUpdatedByUserName = logonUser.UserName;
            activityInstance.LastUpdatedDateTime = System.DateTime.Now;
            Update(activityInstance   );
        }

        /// <summary>
        /// 活动实例完成
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="logonUser"></param>
        /// <param name="session"></param>
        public void Complete(long activityInstanceID, 
            WfLogonUser logonUser )
        {
            var activityInstance = GetById(activityInstanceID);
            activityInstance.State = (short)NodeStateEnum.Completed;
            activityInstance.IsActivityCompleted = 1;
            activityInstance.LastUpdatedByUserID = logonUser.UserID;
            activityInstance.LastUpdatedByUserName = logonUser.UserName;
            activityInstance.LastUpdatedDateTime = System.DateTime.Now;
            activityInstance.EndedByUserID = logonUser.UserID;
            activityInstance.EndedByUserName = logonUser.UserName;
            activityInstance.EndedDateTime = System.DateTime.Now;

            Update(activityInstance);
        }
        #endregion

        internal void Insert(WfActivityInstance entity)
        { 
             ActivityInstanceRepository.Add(entity);

            Debug.WriteLine(string.Format("activity instance inserted, ProcessInstanceID:{0}, time:{1}", entity.ProcessInstanceID ,
                System.DateTime.Now.ToString()));
        }

        internal void Update(WfActivityInstance entity )
        {
            ActivityInstanceRepository.Update(entity );
        }

        /// <summary>
        /// 删除活动实例
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="wfLinqDataContext"></param>
        internal void Delete(long activityInstanceID)
        {
            ActivityInstanceRepository.Delete<WfActivityInstance>(activityInstanceID);
        }
    }
}
